/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.formserver.vmmanager.metadataeventlistener;

import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bff.engine.core.cache.BffEngineCacheService;
import com.inspur.edp.cef.entity.config.CefConfig;
import com.inspur.edp.formserver.viewmodel.GspViewModel;
import com.inspur.edp.formserver.viewmodel.common.LinkBeUtils;
import com.inspur.edp.formserver.viewmodel.common.mapping.GspVoObjectSourceType;
import com.inspur.edp.formserver.viewmodel.exception.ViewModelException;
import com.inspur.edp.formserver.viewmodel.extendinfo.api.GspVoExtendInfoService;
import com.inspur.edp.formserver.viewmodel.extendinfo.entity.GspVoExtendInfo;
import com.inspur.edp.formserver.viewmodel.extendinfo.entity.VoConfigCollectionInfo;
import com.inspur.edp.formserver.vmmanager.exception.VoManagerErrorCodes;
import com.inspur.edp.formserver.voextendinfo.server.api.GspVoExtendInfoRpcService;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.entity.ProcessMode;
import com.inspur.edp.metadata.rtcustomization.api.CustomizationRtService;
import com.inspur.edp.metadata.rtcustomization.api.entity.EnvironmentEnum;
import com.inspur.edp.metadata.rtcustomization.serverapi.CustomizationRtServerService;
import com.inspur.edp.metadata.rtcustomization.spi.event.IMetadataRtEventListener;
import com.inspur.edp.metadata.rtcustomization.spi.event.MetadataRtEventArgs;
import io.iec.edp.caf.boot.context.CAFContext;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class BffMetadataRtEventListener implements IMetadataRtEventListener {
    @Override
    public void fireGeneratedMetadataSavingEvent(MetadataRtEventArgs args) {

    }

    private static final Logger logger = LoggerFactory.getLogger(BffMetadataRtEventListener.class);

    @Override
    public void fireGeneratedMetadataSavedEvent(MetadataRtEventArgs args) {
    }

    @Override
    public void fireMetadataSavingEvent(MetadataRtEventArgs args) {

    }

    @Override
    public void fireMetadataSavedEvent(MetadataRtEventArgs args) {

        GspVoExtendInfoService service = SpringBeanUtils.getBean(GspVoExtendInfoService.class);
        CustomizationRtService customizationService = SpringBeanUtils.getBean(CustomizationRtService.class);
        GspMetadata metadata = args.getMetadata();
        if (metadata.getContent() instanceof GspBusinessEntity) {

            GspBusinessEntity businessEntity = (GspBusinessEntity) metadata.getContent();
            String beId = businessEntity.getId();
            List<GspVoExtendInfo> voExtendInfos = service.getVoId(beId);
            if (voExtendInfos == null || voExtendInfos.size() == 0) {
                return;
            }
            ArrayList<String> metadataLists = new ArrayList<>();
            voExtendInfos.forEach(info -> metadataLists.add(info.getId()));
            customizationService.removeCacheByMetadataIds(metadataLists);
        }

        if (!(metadata.getContent() instanceof GspViewModel)) {
            if ("GSPViewModel".equals(metadata.getHeader().getType())) {
                logger.error("参数中content为null，更新config信息失败！ID:" + metadata.getHeader().getId() + "...name:" + metadata.getHeader().getName());
            }
            return;
        }
        GspViewModel vo = (GspViewModel) metadata.getContent();
        BffEngineCacheService.remove(vo.getID());
        GspVoExtendInfo existed = service.getVoExtendInfo(vo.getID());
        if (existed != null) {
            service.deleteVoExtendInfo(vo.getID());
        }

        try {
            List<GspVoExtendInfo> infos = new ArrayList();
            ProcessMode processMode = args.getProcessMode();
            BffEngineCacheService.remove(vo.getID());
            GspVoExtendInfo info = buildVoExtendInfo(processMode, vo, existed);
            if (metadata.isExtended()) {
                info.setVoConfigCollectionInfo(null);
            }
            if (vo.getGeneratedConfigID() != null) {
                infos.add(info);
                service.saveGspVoExtendInfos(infos);
            }
        } catch (Exception e) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0036, e, vo.getCode(), vo.getName());
        }
    }

    @Override
    public void fireMetadataDeletingEvent(MetadataRtEventArgs args) {

    }

    @Override
    public void fireMetadataDeletedEvent(MetadataRtEventArgs args) {

        GspVoExtendInfoRpcService service = SpringBeanUtils.getBean(GspVoExtendInfoRpcService.class);
        CustomizationRtServerService customizationService = SpringBeanUtils.getBean(CustomizationRtServerService.class);
        GspMetadata metadata = args.getMetadata();
        if ("GspBusinessEntity".equals(metadata.getHeader().getType())) {

            String beId = metadata.getHeader().getId();
            List<GspVoExtendInfo> voExtendInfos = service.getVoId(beId);
            if (voExtendInfos == null || voExtendInfos.size() == 0) {
                return;
            }
            ArrayList<String> metadataLists = new ArrayList<>();
            voExtendInfos.forEach(info -> metadataLists.add(info.getId()));
            customizationService.removeCacheByMetadataIds(metadataLists);
        }

        if (!"GSPViewModel".equals(metadata.getHeader().getType()))
            return;
        BffEngineCacheService.remove(args.getMetadata().getHeader().getId());
        GspVoExtendInfo existed = service.getVoExtendInfo(args.getMetadata().getHeader().getId());
        if (existed != null) {
            service.deleteVoExtendInfo(args.getMetadata().getHeader().getId());
        }

    }

    public void fireMetadataAchievedEvent(MetadataRtEventArgs args) {
        if (args.getEnv() == EnvironmentEnum.TOOL)
            return;
        GspMetadata metadata = args.getMetadata();
        if (!(metadata.getContent() instanceof GspViewModel))
            return;
        GspViewModel viewModel = (GspViewModel) metadata.getContent();
        if (viewModel.getIsVirtual())
            return;
        if (viewModel.getMainObject().getMapping() != null && viewModel.getMainObject().getMapping().getSourceType() == GspVoObjectSourceType.BeObject) {
            LinkBeUtils linkUtil = new LinkBeUtils(true);
            linkUtil.setIsExtend(metadata.isExtended());
            linkUtil.setMetadata(metadata);
            linkUtil.linkWithBe(viewModel);
        }
    }

    private GspVoExtendInfo buildVoExtendInfo(ProcessMode processMode, GspViewModel vo, GspVoExtendInfo existing) {
        GspVoExtendInfo info = new GspVoExtendInfo();
        VoConfigCollectionInfo voConfigCollectionInfo = getBffConfigCollectionInfo(vo);
        voConfigCollectionInfo.setProjectType(processMode);
        info.setVoConfigCollectionInfo(voConfigCollectionInfo);
        info.setId(vo.getID());
        info.setConfigId(vo.getGeneratedConfigID());
        ;
        info.setCreatedOn(Date.from(CAFContext.current.getCurrentDateTime().toInstant()));
        info.setLastChangedOn(Date.from(CAFContext.current.getCurrentDateTime().toInstant()));
        if (!vo.getIsVirtual()) {
            info.setBeSourceId(vo.getMapping().getTargetMetadataId());
        }
        if (existing != null) {
            info.setLastChangedOn(Date.from(CAFContext.current.getCurrentDateTime().toInstant()));
        }
        return info;
    }

    private VoConfigCollectionInfo getBffConfigCollectionInfo(GspViewModel vo) {
        CefConfig cefConfig = new CefConfig();
        cefConfig.setID(vo.getGeneratedConfigID());
        cefConfig.setDefaultNamespace(vo.getCoreAssemblyInfo().getDefaultNamespace().toLowerCase());
        VoConfigCollectionInfo voConfigCollectionInfo = new VoConfigCollectionInfo();
        voConfigCollectionInfo.setConfig(cefConfig);
        return voConfigCollectionInfo;
    }
}
